//import org.cloudbus.cloudsim.Host;
//import org.cloudbus.cloudsim.HostDynamicWorkload;
//import org.cloudbus.cloudsim.HostStateHistoryEntry;
//import org.cloudbus.cloudsim.power.PowerHost;
//import runner.PSO.SchedulerParticle;
//import runner.jswarm_pso.FitnessFunction;
//
//import java.math.BigDecimal;
//import java.text.DecimalFormat;
//import java.util.*;
//
//public class SchedulerFitnessFunction1 extends FitnessFunction {
//
//    private double[][] hostsRemainCapacity;
//    private double[][] vmsRequestCapacity;
//    private static SchedulerParticle particles[];
//
//    private static List<PowerHost> availableHosts;
//    private static int[] HostsId;
////    private List<Vm> vmList;
//
//    public SchedulerFitnessFunction1(double[][] hostsRemainCapacity, double[][] vmsRequestCapacity, SchedulerParticle[] particles, List<PowerHost> availableHosts){
//        super(false);      // maximize设置为false：表示最小化适应度函数
//        setHostsRemainCapacity(hostsRemainCapacity);
//        setVmsRequestCapacity(vmsRequestCapacity);
//        setParticles(particles);
//        setHostList(availableHosts);
////        setVmList(vmList);
//
//        HostsId = new int[availableHosts.size()];
//        int k = 0;
//        for (Host h : availableHosts) {
//            HostsId[k] = h.getId();
//            k++;
//        }
//    }
//
//    /*public SchedulerFitnessFunction1(List<PowerHost> appreciateHosts) {
//        super(false);
//        setHostList(appreciateHosts);
//    }*/
//
//    private List<Integer> placeVmbyPosition(double[][] Remain, double[][] Request, double[] position) {
//        List<Integer> placeSet = new ArrayList<Integer>();
//        //double[] position = particle.getPosition();
//
//        int times = 0;  // 用来存储主机id值的下标，方便remain的查找
//        for (int i=0; i<position.length; i++) {
//            int place = (int) position[i];
//            /*for (int id=0; id<HostsId.length; id++)
//                if (place == HostsId[id]) {
//                    index = id;
//                    break;
//                }*/
//
//            double[] hostRemainCapacity = Remain[place];
//            int flag = isFit(Request[i], hostRemainCapacity);
//            if (flag != -1) {
//                // 若该主机(id=place)的资源剩余量满足当前vm的资源请求量
//                // 则将该主机上的资源减去请求的，表示将当前vm放置在该主机上
//                Remain[place][0] -= Request[i][0];
//                Remain[place][1] -= Request[i][1];
//                Remain[place][2] -= Request[i][2];
//            } else {
//                for (int j=0; j<Remain.length; j++) {
//                    int g = isFit(Request[i], Remain[j]);
//                    if (g != -1) {
//                        place = j;
//                        position[i] = place;
//                        Remain[place][0] -= Request[i][0];
//                        Remain[place][1] -= Request[i][1];
//                        Remain[place][2] -= Request[i][2];
//                        break;
//                    }
//                }
//            }
//            if (!placeSet.contains(place)) {
//                placeSet.add(place);
//            }
//
//            /*int flag = isFit(Request[i], Remain[place]);  // 判断当前主机剩余资源是否满足当前vm请求的资源
//            if (flag == -1) {  // =-1不满足
//                // 顺序查找一个满足当前vm要求的主机
//                for (int j=0; j<Remain.length; j++) {
//                    if (j == place) continue;
//                    int g = isFit(Request[i], Remain[j]);
//                    if (g != -1) {  // !=-1 可以放置
//                        place = j;
//                        position[i] = j;  // 修改位置
//                        //times++;  // 记录修改了多少次
//                        if (g == 0) Remain[j][0] -= Request[i][0];  // 第一个核被分配
//                        else Remain[j][1] -= Request[i][0];         // 第二个核被分配
//                        break;
//                    }
//                }
//            } else {
//                if (flag == 0) Remain[place][0] -= Request[i][0];
//                else Remain[place][1] -= Request[i][0];
//            }
//            Remain[place][2] -= Request[i][1];
//            Remain[place][3] -= Request[i][2];
//            if (!placeSet.contains(place)) {
//                placeSet.add(place);
//            }*/
////            int flag = isFit(Request[i], Remain[place]);
////            while (flag == -1) {
////                times++;
////                if (times >= Remain.length)
////                    return null;
////            }
////            Remain[place][0] -= Request[i][0];
////            Remain[place][1] -= Request[i][1];
////            Remain[place][2] -= Request[i][2];
////            if (!placeSet.contains(place)) {
////                placeSet.add(place);
////            }
//        }
//        return placeSet;
//    }
//
//    public int isFit(double[] vmRequest, double[] hostRemainCapacity){
//        /*int flag = -1;  // flag=-1 表示主机提供的资源量不满足当前vm请求的
//        //boolean flag = true;
//        // 有任意一种资源不满足，直接返回-1
//        if(vmRequest[0] > hostRemainCapacity[0]){
//            //flag = 0;
//            if (vmRequest[0] > hostRemainCapacity[1]) return flag; //不符合直接返回
//            else flag = 1;  // 为1表示主机peList[1]满当前vm的请求
//        } else flag = 0;   // 为0表示主机peList[0]满当前vm的请求
//        for(int i=2; i<vmRequest.length; i++){
//            if (vmRequest[i-1] > hostRemainCapacity[i]) {
//                flag = -1;
//                break;
//            }
//        }
//        return flag;*/
//
//        int flag = 1;
//        for (int i=0; i<vmRequest.length; i++) {
//            if (vmRequest[i] > hostRemainCapacity[i]) {
//                flag = -1;
//                break;
//            }
//        }
//        return flag;
//    }
//
//    private Map<Object, Object> getFitnessValue(double[][] originalRemain, double[][] tempRemain, List<Integer> placeSet) {
//        Map<Object, Object> fitness = new HashMap<>();
//        List<PowerHost> hosts = new LinkedList<>();
//        double[] U = new double[originalRemain.length];   // 物理主机j的资源利用率U
//        double[] Ram = new double[originalRemain.length];   // 物理主机j的资源利用率Ram
//        double[] Bw = new double[originalRemain.length];   // 物理主机j的资源利用率Bw
//
//        double[][] Re = new double[originalRemain.length][3];   // 物理主机j的资源剩余率Re
//        double[] ReAvg = new double[originalRemain.length];
//        double[] ReRemain = new double[originalRemain.length];
//        double energy = 0.0;
//        double alpha = 0.67;
//        double reRemain = 0.0;     // 资源剩余率
//        double sla = 0.0;          // SLA服务水平协议违例率
//        double slatah = 0.0;
//
//        //int activeHosts = placeSet.size();
//        for(int j : placeSet){  // j取出的是集合中的值
////          当前主机j的利用率
////            U[j] = ((originalRemain[j][0]+originalRemain[j][1]) - (tempRemain[j][0]+tempRemain[j][1])) / (originalRemain[j][0]+originalRemain[j][1]);    // 当前主机的cpu利用率
//            U[j] = (originalRemain[j][0] - tempRemain[j][0]) / originalRemain[j][0];
//            Ram[j] = (originalRemain[j][1] - tempRemain[j][1]) / originalRemain[j][1];
//            Bw[j] = (originalRemain[j][2] - tempRemain[j][2]) / originalRemain[j][2];
//
//            PowerHost host = availableHosts.get(j);
//            hosts.add(host);
//            energy += (1-U[j])*alpha*host.getMaxPower() + host.getMaxPower()*U[j];
//            /*fv += (originalRemain[i][2] - tempRemain[i][2])/originalRemain[i][2];
//            fv += (originalRemain[i][3] - tempRemain[i][3])/originalRemain[i][3];*/
////          主机j的SLA违例率
////            sla += 1 / (1 + Math.pow(Math.E, U[j]-0.9));
//            double u = 0.5*U[j] + 0.25*Ram[j] + 0.25*Bw[j];
//            sla += Math.log(2 + u - 0.9);
//
////          计算主机j各资源剩余率
//           /* Re[j][0] = (tempRemain[j][0]+tempRemain[j][1]) / (originalRemain[j][0]+originalRemain[j][1]); // cpu资源剩余量/cpu资源总量
//            Re[j][1] = tempRemain[j][2] / originalRemain[j][2];         // Ram(内存)资源剩余量/Ram资源总量
//            Re[j][2] = tempRemain[j][3] / originalRemain[j][3];         // Bw(带宽)资源剩余量/bw资源总量*/
//            Re[j][0] = tempRemain[j][0] / originalRemain[j][0];
//            Re[j][1] = tempRemain[j][1] / originalRemain[j][1];
//            Re[j][2] = tempRemain[j][2] / originalRemain[j][2];
//            // 加权和——标准差——资源均衡
//            ReAvg[j] = 0.35*Re[j][0] + 0.35*Re[j][1] + 0.30*Re[j][2];
////            ReAvg[j] = (Re[j][0] + Re[j][1] + Re[j][2]) / 3;
//            ReRemain[j] = Math.sqrt(
//                    ( Math.pow(Re[j][0]-ReAvg[j], 2) + Math.pow(Re[j][1]-ReAvg[j], 2) + Math.pow(Re[j][2]-ReAvg[j], 2) ) / 3
//            );
//            reRemain += ReRemain[j];
//        }
////        energy /= placeSet.size();
////        sla /= placeSet.size();
////        reRemain /= placeSet.size();
//
////        计算SLATAH 即出现单个活动主机的SLA违例
////        slatah = getSlaTAH(hosts);
//
//        /* return 0.4*energy + 0.3*reRemain + 0.3*sla;  sla相对来说会减少一点，但能耗值相对增加一点或者不变*/
//
////        DecimalFormat d = new DecimalFormat("#.00000");  // 会返回String类型
////        BigDecimal.ROUND_HALF_UP : 表示四舍五入
//        fitness.put(1, (new BigDecimal(energy).setScale(5, BigDecimal.ROUND_HALF_UP)).doubleValue() );
//        fitness.put(2, (new BigDecimal(reRemain).setScale(5, BigDecimal.ROUND_HALF_UP)).doubleValue() );
//        fitness.put(3, (new BigDecimal(sla).setScale(5, BigDecimal.ROUND_HALF_UP)).doubleValue() );
////        fitness.put(1, (double)Math.round(energy*100000)/100000 );
////        fitness.put(2, (double)Math.round(reRemain*100000)/100000 );
////        fitness.put(3, (double)Math.round(sla*100000)/100000 );
//        return fitness;
//    }
//
//    @Override
//    public Map<Object, Object> evaluate(double[] position) {
//        //double[] location = new double[position.length];
//        Map<Object, Object> fk = new HashMap<>();
//        double[][] tempRemain = new double[hostsRemainCapacity.length][3];
//
//        for(int i=0; i<tempRemain.length; i++){
//            for(int j=0; j<tempRemain[0].length; j++){
//                tempRemain[i][j] = hostsRemainCapacity[i][j];
//            }
//        }
//
//        List<Integer> placeSet = placeVmbyPosition(tempRemain, vmsRequestCapacity, position);  // 该集合存储使用主机的下标
//        if (placeSet == null) {
//            double bestFit = (isMaximize() ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
//            fk.put(1, bestFit);
//            fk.put(1, bestFit);
//            fk.put(1, bestFit);
//        } else {
//            // 计算该粒子的适应度值
//            fk = getFitnessValue(hostsRemainCapacity, tempRemain, placeSet);   // 这里的tempRemain剩余资源量是否是放置后剩余的？
//            for(int i=0; i<tempRemain.length; i++){
//                for(int j=0; j<tempRemain[0].length; j++){
//                    tempRemain[i][j] = hostsRemainCapacity[i][j];
//                }
//            }
//        }
//        return fk;
//    }
//
//    public static List<PowerHost> getHostList() {
//        return availableHosts;
//    }
//
//    public static void setHostList(List<PowerHost> hostList) {
//        SchedulerFitnessFunction1.availableHosts = hostList;
//    }
//
//    /*public List<Vm> getVmList() {
//        return vmList;
//    }
//
//    public void setVmList(List<? extends Vm> vmList) {
//        this.vmList = (List<Vm>) vmList;
//    }*/
//
//    public void setHostsRemainCapacity(double[][] hostsRemainCapacity) {
//        this.hostsRemainCapacity = hostsRemainCapacity;
//    }
//
//    public void setVmsRequestCapacity(double[][] vmsRequestCapacity) {
//        this.vmsRequestCapacity = vmsRequestCapacity;
//    }
//
//    public static void setParticles(SchedulerParticle1[] particles) {
//        SchedulerFitnessFunction1.particles = particles;
//    }
//
//    /**
//     * Gets the sla time per active host.
//     *
//     * @param hosts the hosts
//     * @return the sla time per active host
//     */
//    protected static double getSlaTAH(List<PowerHost> hosts) {
//        double slaViolationTimePerHost = 0;
//        double totalTime = 0;
//
//        for (PowerHost _host : hosts) {
//            HostDynamicWorkload host = _host;
//            double previousTime = -1;
//            double previousAllocated = 0;
//            double previousRequested = 0;
//            boolean previousIsActive = true;
//
//            for (HostStateHistoryEntry entry : host.getStateHistory()) {
//                if (previousTime != -1 && previousIsActive) {
//                    double timeDiff = entry.getTime() - previousTime;
//                    totalTime += timeDiff;
//                    if (previousAllocated < previousRequested) {
//                        slaViolationTimePerHost += timeDiff;
//                    }
//                }
//
//                previousAllocated = entry.getAllocatedMips();
//                previousRequested = entry.getRequestedMips();
//                previousTime = entry.getTime();
//                previousIsActive = entry.isActive();
//            }
//        }
//
//        return slaViolationTimePerHost / totalTime;
//    }
//
//}
